package com.wc.算法提高课.E第五章_数学知识.高斯消元.球形空间产生器;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;

/**
 * @Author congge
 * @Date 2024/10/9 20:43
 * @description https://www.acwing.com/problem/content/description/209/
 */
public class Main {
    /**
     * 思路：<p>
     * 球心: (x[1], x[2], x[3], ..., x[n])<p>
     * 球上的点 (a[i][1], a[i][2], a[i][3], ... , a[i][n])<p>
     * 点到球心距离 R <p>
     * 第i行 ：(a[i][1] - x[1])^2 + (a[i][2] - x[2])^2 + (a[i][3] - x[3])^2 + ... + (a[i][n] - x[n])^2 = R^2 <p>
     * 第 i + 1行 - i 行<p>
     * 2(a[i + 1][1] - a[i][1]) x[1] + 2(a[i + 1][2] - a[i][2])x[2] + ... + 2(a[i + 1][n] - a[i][n])x[n] = <p>
     * a[i + 1][1]^2 + a[i + 1][2]^2 + ... + a[i + 1][n]^2 - a[i][1]^2 - a[i][2]^2 - ... - a[i][n]^2<p>
     * 都减去第一行, 可得到 n行 n列矩阵,求解 n 位方程, 高斯消元即可<p>
     */
    static FastReader sc = new FastReader();
    static PrintWriter out = new PrintWriter(System.out);
    static int N = 15;
    static double[][] a = new double[N][N], b = new double[N][N];
    static int n;

    public static void main(String[] args) {
        n = sc.nextInt();
        for (int i = 0; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                a[i][j] = sc.nextDouble();
            }
        }
        // 构造b
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                b[i][j] += 2 * (a[i][j] - a[0][j]);
                b[i][n + 1] += a[i][j] * a[i][j] - a[0][j] * a[0][j];
            }
        }
        gauss();
        for(int i = 1; i <= n; i++){
            out.printf("%.3f ", b[i][n + 1]);
        }
        out.flush();
    }

    static void gauss() {
        // 形成上三角
        for (int r = 1, c = 1; r <= n; r++, c++) {
            // 主元
            int t = r;
            for (int i = r + 1; i <= n; i++) {
                if (Math.abs(b[i][c]) > Math.abs(b[t][c]))
                    t = i;
            }
            // 交换
            swap(b, t, r);
            // 归一
            for (int i = n + 1; i >= c; i--) {
                b[r][i] /= b[r][c];
            }
            // 消除
            for (int i = r + 1; i <= n; i++) {
                for (int j = n + 1; j >= c; j--) {
                    b[i][j] -= b[i][c] * b[r][j];
                }
            }
        }
        // 形成对角矩阵, 一列一列来
        for (int j = n; j > 1; j--) {
            for (int i = j - 1; i >= 1; i--) {
                b[i][n + 1] -= b[i][j] * b[j][n + 1];
                b[i][j] = 0;
            }
        }
    }

    static void swap(double[][] a, int i, int j) {
        double[] tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
    }
}

class FastReader {
    StringTokenizer st;
    BufferedReader br;

    FastReader() {
        br = new BufferedReader(new InputStreamReader(System.in));
    }

    String next() {
        while (st == null || !st.hasMoreElements()) {
            try {
                st = new StringTokenizer(br.readLine());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return st.nextToken();
    }

    int nextInt() {
        return Integer.parseInt(next());
    }

    String nextLine() {
        String s = "";
        try {
            s = br.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return s;
    }

    long nextLong() {
        return Long.parseLong(next());
    }

    double nextDouble() {
        return Double.parseDouble(next());
    }

    // 是否由下一个
    boolean hasNext() {
        while (st == null || !st.hasMoreTokens()) {
            try {
                String line = br.readLine();
                if (line == null)
                    return false;
                st = new StringTokenizer(line);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return true;
    }
}
